#include <stdio.h>
#include <getopt.h>

#include "../util.h"
#include "../verb/encrypt.h"
#include "../action/encrypt.h"

_Noreturn void verb_encrypt_usage(FILE *restrict out) {
    fputs("Usage: " PROGRAM_NAME " encrypt [OPTIONS] PASSWORD\n", out);
    fputs("Encrypt password using specififed exponent and modulus.\n", out);
    fputs("\n", out);
    fputs("Options:\n", out);
    fputs("  -e, --exponent=EXPONENT    encrypt with EXPONENT\n", out);
    fputs("  -m, --modulus=MODULUS      enctypt with MODULUS\n", out);
    fputs("  --help                     display this help and exit\n", out);
    fputs("\n", out);
    fputs("Exit status:\n", out);
    fputs(" 0  if successfully encrypted\n", out);
    fputs(" 1  if exponent or modulus is missing\n", out);
    fputs(" 2  if exponent or modulus is invaild\n", out);
    exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}

int verb_encrypt(const int argc, char* const* argv) {
    int lose = 0;
    static struct option long_options[] = {
        {"exponent",  required_argument,  NULL, 'e' },
        {"modulus",   required_argument,  NULL, 'm' },
        {"help",      no_argument,        NULL, 'h' },
        {0,           0,                  0,     0 }
    };
    const char* encrypt_exponent = NULL;
    const char* encrypt_password = NULL;
    const char* encrypt_modulus  = NULL;
    
    while (1) {
        int c = getopt_long(argc, argv, "-e:m:h", long_options, NULL);

        if (c == -1) {
            break;
        }

        switch (c) {
            case 'h':
                verb_encrypt_usage(stdout);
                break;
        
            case 'e':
                encrypt_exponent = optarg;
                break;
        
            case 'm':
                encrypt_modulus = optarg;
                break;
            
            case 1:
                if (encrypt_password != NULL) {
                    error(0, 0, "exceed argument: %s", optarg);
                    verb_encrypt_usage(stderr);
                }
                encrypt_password = optarg;
                break;

            default:
                lose = 1;
                break;
        }
    }

    if (lose) {
        verb_encrypt_usage(stderr);
    }
    
    if (encrypt_password == NULL) {
        if (GLOBAL_ARGS.auth_password == NULL) { 
            error(0, 0, "No password provided.");
            exit(EXIT_FAILURE);
        } else {
            encrypt_password = GLOBAL_ARGS.auth_password;
        }
    }
    
    if (encrypt_exponent == NULL || strlen(encrypt_exponent) == 0) {
        error(0, 0, "No exponent provided.");
        exit(EXIT_FAILURE);
    }
    
    if (encrypt_modulus == NULL || strlen(encrypt_modulus) == 0) {
        error(0, 0, "No modulus provided.");
        exit(EXIT_FAILURE);
    }
    
    action_encrypt_result result = action_encrypt(
        encrypt_password,
        encrypt_exponent,
        encrypt_modulus
    );
    
    if (result.status == ACTION_ENCRYPTING_PARSE_FAILURE) {
        return 2;
    }
    // TODO add more status
    
    puts(result.encrypted_string);
    free(result.encrypted_string);
    
    return 0;
}
